<?php

namespace yphp;

final class Yphp
{
    # 定义只能执行一次的变量
    private static $once = false;
    // 引入文件数组
    protected static $fileArr = [];
    // 对照表，类名前缀 和 路径前缀对照
    protected static $className = ['yphp\\' => CORE, 'app\model\\' => MODEL, 'app\controller\\' => CONTROLLER];

    // 初始化
    static function init()
    {
        if (self::$once) return;
        self::$once == true;
        # 引入框架的助手函数
        self::loadfile(YP . 'helper.php');
        # 引入应用公共函数
        self::loadfile(APP_PATH . 'common.php');
        # 调试模式
        define('DEBUG', Config::web('app_debug'));
        # 路由分隔符..
        define('ROUTELINE', Config::web('route_line'));
        # 时区
        date_default_timezone_set(Config::web('timezone'));
        # 表示是命令行操作还是网页操作，本身是final类，所以调用的是本身的cmd和web方法
        PHP_SAPI === 'cli' ? (new static)->cmd() : (new static)->web();
    }

    // 网页
    private function web()
    {
        define('IS_CLI', false);
        Response::instance()->export();
    }

    // 指令
    private function cmd()
    {
        define('IS_CLI', true);
        /**
         * 使用方式
         * php operation 参数...
         * ./operation 参数....
         */
//        print_r($_SERVER['argc']);
//        print_r($_SERVER['argv']);

        $args = $_SERVER['argv'];
        array_shift($args);
        call_user_func('\yphp\\' . ucfirst($args[0]));

        self::showError(call_user_func('\yphp\\' . ucfirst($args[0])));

    }

    // 引入文件
    static function loadfile($filename)
    {
        return key_exists($filename, self::$fileArr) ? self::$fileArr[$filename] : self::$fileArr[$filename] = is_file($filename) ? include $filename : null;
    }

    // 类加载
    static function load($class)
    {
        $classArr = self::searchClass($class);
        $filename = self::$className[$classArr[0]] . str_replace('\\', DS, $classArr[1]) . '.php';
        is_file($filename) ? include $filename : self::showError($class . '类文件不存在');
    }

    // 检索类名
    static function searchClass($class)
    {
        $classval = false;
        foreach (self::$className as $key => $value) {
            if (strpos($class, $key) === 0) {
                $classval = [$key, substr($class, strlen($key))];
                break;
            }
        }
        if (!$classval) self::showError($class . '类不属于框架自加载类');
        return $classval;
    }

    // 获取错误类型
    private static function type($code)
    {
        $name = 'Other';
        foreach (self::$errorTypes as $k => $v) {
            if (in_array($code, $v)) {
                $name = $k;
                break;
            }
        }
        return $name;
    }

    // 类型数组
    private static $errorTypes = [
        'Fatal Error' => [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR],
        'Parse Error' => [E_PARSE],
        'Warning' => [E_WARNING, E_CORE_WARNING, E_COMPILE_WARNING, E_USER_WARNING],
        'Notice' => [E_NOTICE, E_USER_NOTICE],
    ];

    // 致命错误
    static function fatal()
    {
        if ($e = error_get_last()) self::error($e['type'], $e['message'], $e['file'], $e['line']);
    }

    // 错误输出
    static function error($code, $msg, $file, $line)
    {
        self::showError(' 错误类型 [ '. self::type($code) .' ] '. PHP_EOL .' 错误信息 [ ' . $msg . ' ] '. PHP_EOL .' 错误文件 [ ' . preg_replace('/^' . preg_quote(ROOT_PATH, DS) . '/', '', $file) . '  ' . $line.' 行 ]');
    }

    // 异常错误
    static function exception($e)
    {
//        dump($e->getTrace());
        return self::error($e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine());
    }

    // 错误显示
    static function showError($msg)
    {
        IS_CLI ? call_user_func(function () use ($msg) {
            print_r($msg);
        }) : call_user_func(function () use ($msg) {
            echo '<pre style="padding:10px;margin:15px 10px;font-size:14px;line-height:1.5;color:#333;background:#ccc;border:1px solid #ccc;border-radius:4px;overflow-x:auto">';
            print_r($msg);
            echo '</pre>';
            die;
        });
    }



}